package com.tyut.musicdreamer.framework.starter.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis配置类
 */
@Slf4j
@Configuration
public class RedisConfiguration {

    @Value("${spring.data.redis.host:localhost}")
    private String host;

    @Value("${spring.data.redis.port:6379}")
    private int port;

    @Value("${spring.data.redis.password:}")
    private String password;

    @Value("${spring.data.redis.database:0}")
    private int database;
    
    /**
     * 创建Redis专用的ObjectMapper
     */
    @Bean
    public ObjectMapper redisObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        
        // 设置序列化和反序列化特性
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        
        // 注册Java 8日期时间模块
        objectMapper.registerModule(new JavaTimeModule());
        
        return objectMapper;
    }
    
    /**
     * 创建String类型的Redis序列化器
     */
    @Bean
    public RedisSerializer<String> stringRedisSerializer() {
        return new StringRedisSerializer();
    }
    
    /**
     * 创建Jackson JSON类型的Redis序列化器
     */
    @Bean
    public RedisSerializer<Object> jacksonRedisSerializer(ObjectMapper redisObjectMapper) {
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        serializer.setObjectMapper(redisObjectMapper);
        return serializer;
    }
    
    /**
     * 创建RedisConnectionFactory
     */
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        log.info("初始化Redis连接工厂，host: {}, port: {}, database: {}", host, port, database);
        
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(host);
        config.setPort(port);
        if (password != null && !password.isEmpty()) {
            config.setPassword(password);
        }
        config.setDatabase(database);
        
        return new LettuceConnectionFactory(config);
    }
    
    /**
     * 创建RedisTemplate
     * 使用全局统一的序列化配置
     */
    @Bean
    @Primary
    public RedisTemplate<String, Object> redisTemplate(
            RedisConnectionFactory connectionFactory,
            RedisSerializer<String> stringRedisSerializer,
            RedisSerializer<Object> jacksonRedisSerializer) {
        
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用全局统一的序列化器
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(jacksonRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(jacksonRedisSerializer);
        
        template.afterPropertiesSet();
        return template;
    }
    
    /**
     * 创建RedissonClient
     */
    @Bean
    public RedissonClient redissonClient() {
        log.info("初始化Redisson客户端，host: {}, port: {}, database: {}", host, port, database);
        
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://" + host + ":" + port)
                .setPassword(password.isEmpty() ? null : password)  // 如果密码为空，则设置为null
                .setDatabase(database)
                .setConnectionMinimumIdleSize(1)
                .setConnectionPoolSize(4)
                .setRetryAttempts(5)
                .setRetryInterval(1000)
                .setConnectTimeout(5000)
                .setIdleConnectionTimeout(10000)
                .setTimeout(3000);
        
        try {
            RedissonClient client = Redisson.create(config);
            log.info("Redisson客户端初始化成功");
            return client;
        } catch (Exception e) {
            log.error("Redisson客户端初始化失败: {}", e.getMessage(), e);
            throw e;
        }
    }
} 